package com.smart.sso.server.service.impl;

import com.smart.mvc.model.Pagination;
import com.smart.mvc.model.Result;
import com.smart.mvc.model.ResultCode;
import com.smart.mvc.service.mybatis.impl.ServiceImpl;
import com.smart.sso.rpc.UserRpcDto;
import com.smart.sso.server.dao.UserDao;
import com.smart.sso.server.dto.OrgUserDto;
import com.smart.sso.server.enums.TrueFalseEnum;
import com.smart.sso.server.model.Org;
import com.smart.sso.server.model.Role;
import com.smart.sso.server.model.User;
import com.smart.sso.server.model.UserRole;
import com.smart.sso.server.provider.PasswordProvider;
import com.smart.sso.server.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;

@Service("userService")
public class UserServiceImpl extends ServiceImpl<UserDao, User, Integer> implements UserService {
	
	@Resource
	private UserRoleService userRoleService;
	@Resource
	private AppService appService;
	@Resource
	private RoleService roleService;
	@Resource
	private UserUserService userUserService;
	@Resource
	private OrgService orgService;

	@Autowired
	public void setDao(UserDao dao) {
		this.dao = dao;
	}
	
	public Result login(String ip, String account, String password) {
		Result result = Result.createSuccessResult();
		User user = findByAccount(account);
		if (user == null) {
			result.setCode(ResultCode.ERROR).setMessage("登录名不存在");
		}
		else if (!user.getPassword().equals(password)) {
			result.setCode(ResultCode.ERROR).setMessage("密码不正确");
		}
		else if (TrueFalseEnum.FALSE.getValue().equals(user.getIsEnable())) {
			result.setCode(ResultCode.ERROR).setMessage("已被用户禁用");
		}
		else {
			user.setLastLoginIp(ip);
			user.setLoginCount(user.getLoginCount() + 1);
			user.setLastLoginTime(new Date());
			dao.update(user);
			result.setData(user);
		}
		return result;
	}

	public void enable(Boolean isEnable, List<Integer> idList,Integer updateUserId,Date updateTime) {
		verifyRows(dao.enable(isEnable, idList,updateUserId,updateTime), idList.size(), "用户数据库更新失败");
	}
	
	public void save(User t) {
		super.save(t);
	}

	public void resetPassword(String password, List<Integer> idList) {
		verifyRows(dao.resetPassword(password, idList), idList.size(), "用户密码数据库重置失败");
	}

	public Pagination<User> findPagination(String isEnabel,Integer orgId,String account,String realName,String mobile, Pagination<User> p) {
		dao.findPagination(isEnabel,orgId,account,realName,mobile, p);
		return p;
	}
	
	public User findByAccount(String account) {
		return dao.findByAccount(account);
	}
	
	@Transactional
	public void deleteById(List<Integer> idList) {
		userRoleService.deleteByUserIds(idList);
		verifyRows(dao.deleteById(idList), idList.size(), "用户数据库删除失败");
	}

	@Override
	public void updatePassword(Integer id, String newPassword) {
		User user = get(id);
		user.setPassword(PasswordProvider.encrypt(newPassword));
		update(user);
	}
	

	@Override
	public void save(User user, List<Integer> roleIdList,List<Integer> leaderOrgIdList,List<Integer> lowerOrgIdList) {
		save(user);
		List<UserRole> userRoleList = new ArrayList<UserRole>();
		UserRole bean;
		for (Integer roleId : roleIdList) {
			bean = new UserRole();
			bean.setUserId(user.getId());
			bean.setRoleId(roleId);
			userRoleList.add(bean);
		}
		userRoleService.allocate(user.getId(), userRoleList);
		saveDataRange(user,leaderOrgIdList,lowerOrgIdList);
	}
	
	/**
	 * 更新数据权限
	 * @param user 用户
	 * @param leaderOrgIdList 上级部门id（所有上级，不含本部门）
	 * @param lowereOrgIdList 下级部门id（所以下级，不含本部门）
	 * @return
	 */
	@Transactional
	public int saveDataRange(User user,List<Integer> leaderOrgIdList,List<Integer> lowereOrgIdList) {
		Integer userId=user.getId();
		List<Integer> userIdList=Arrays.asList(userId);
		//判断角色权限
		List<Role> roleList=roleService.findListByUserId(userId,null);
		Boolean isSuperAdmin=false;
		Boolean isOrgAdmin=false;
		if(!CollectionUtils.isEmpty(roleList)) {
			for(Role role:roleList) {
				if("superadmin".equals(role.getBusiCode())||"sysadmin".equals(role.getBusiCode())) {
					isSuperAdmin=true;
				}
				else if("orgadmin".equals(role.getBusiCode())) {
					isOrgAdmin=true;
				}
			}
		}
		//超级管理员不用设置权限
		if(isSuperAdmin) {
			return 0;
		}
		//先删除原油的数据权限记录
		userUserService.deleteByChargeUserIds(userIdList);
		userUserService.deleteByUserIds(userIdList);
		
		String[] roleBusiCodes=new String[]{"superadmin","sysadmin"};
		
		List<Org> allOrgList=orgService.findByAll(null, null, null);
		
		//上级被管理
		List<User> leaderList=new ArrayList<User>();
		if(CollectionUtils.isEmpty(leaderOrgIdList)) {
			leaderOrgIdList=new ArrayList<Integer>();
			loopLowerOrgList(user.getOrgId(),leaderOrgIdList,allOrgList);
		}
		if(!CollectionUtils.isEmpty(leaderOrgIdList)) {
			leaderList=this.findByOrgId(leaderOrgIdList, roleBusiCodes,null);
		}
		
		if (!CollectionUtils.isEmpty(leaderList)) {
			for(User userTemp:leaderList) {
				userUserService.allocate(false,userTemp.getId(), userIdList);
			}
			
		}
		
		//下级管理
		List<User> lowerList=new ArrayList<User>();
		if(CollectionUtils.isEmpty(lowereOrgIdList)) {
			lowereOrgIdList=new ArrayList<Integer>();
			loopLeaderOrgList(user.getOrgId(),lowereOrgIdList,allOrgList);
		}
		if(!CollectionUtils.isEmpty(lowereOrgIdList)) {
			lowerList=this.findByOrgId(lowereOrgIdList, roleBusiCodes,null);
		}
		
		if(isOrgAdmin) {
			//若是部门管理员，则管理本部门所有人
			Integer orgId=user.getOrgId();
			List<User> sameOrgUser=this.findByOrgId(Arrays.asList(orgId),roleBusiCodes, null);
			if (!CollectionUtils.isEmpty(sameOrgUser)) {
				lowerList.addAll(sameOrgUser);
			}
		}
		else {
			//若不是部门管理员,则只自己管理自己
			lowerList.add(user);
		}
		
		if (!CollectionUtils.isEmpty(lowerList)) {
			List<Integer> lowerUserIdList=new ArrayList<Integer>();
			for(User userTemp:lowerList) {
				lowerUserIdList.add(userTemp.getId());
			}
			userUserService.allocate(false,userId, lowerUserIdList);
		}
		return 0;
	}
	
	// 递归方法，获取所有下级部门
	protected void loopLowerOrgList(Integer id, List<Integer> idList, List<Org> allOrgList) {
		for (Org org : allOrgList) {
			if (id.equals(org.getParentId())) {
				idList.add(org.getId());
				loopLowerOrgList(org.getId(), idList, allOrgList);
			}
		}
	}
	// 递归方法，获取所有上级部门
	protected void loopLeaderOrgList(Integer id, List<Integer> idList, List<Org> allOrgList) {
		for (Org org : allOrgList) {
			//若是根目录则终止本次循环
			if(org.getOrgLevel()==0) {
				continue;
			}
			if (id.equals(org.getParentId())) {
				idList.add(org.getId());
				loopLeaderOrgList(org.getParentId(), idList, allOrgList);
			}
		}
	}

	@Override
	public List<User> findByOrgId(List<Integer> orgIdList,String[] roleBusiCodes, Boolean isEnable) {
		return dao.findByOrgId(orgIdList, roleBusiCodes,isEnable);
	}

	@Override
	public List<User> findByOrgBusiCode(String busiCode, Boolean isEnable) {
		return dao.findByOrgBusiCode(busiCode, isEnable);
	}
	
	
	@Override
	public List<User> findByChargeUserId(Integer chargeUserId,Integer exceptUserId,Boolean isEnable) {
		return dao.findByChargeUserId(chargeUserId,exceptUserId,isEnable);
	}
	
	public List<OrgUserDto> findAllUsers(Boolean isEnable){
		return dao.findAllUsers(isEnable);
	}

	@Override
	public User findByUserCode(String userCode) {
		return dao.findByUserCode(userCode);
	}

	
	@Override
	public List<UserRpcDto> findByIds(List<Integer> idList) {
		return dao.findByIds(idList);
	}


	@Override
	public List<UserRpcDto> findByUserInfo(List<Integer> idList,String[] roleBusiCodes,Map<String,String> params) {
		return dao.findByUserInfo(idList,roleBusiCodes,params);
	}

	@Override
	public List<UserRpcDto> findByUserIdAndRole(List<Integer> idList,String[] roleBusiCodes) {
		return dao.findByUserIdAndRole(idList,roleBusiCodes);
	}

	@Override
	public String genUserCode() {
		Calendar calendar=Calendar.getInstance();
		calendar.setTime(new Date());
		Integer year=calendar.get(Calendar.YEAR);
		String userCodePrifix=String.valueOf(year).substring(2);
		Integer totalCnt=dao.countByUserCodePrifix(userCodePrifix);
		String userCode=userCodePrifix+String.format("%03d", totalCnt+1);
		return userCode;
	}

	@Override
	public User findByQiyeWxUserId(String qiyeWxUserId) {
		return this.dao.findByQiyeWxUserId(qiyeWxUserId);
	}

	@Override
	public List<User> findByManagedUserId(Integer managedUserId, Integer exceptUserId) {
		return dao.findByManagedUserId(managedUserId, exceptUserId);
	}
}
